/**
* @file venc_processor.cpp
*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "video_processor.h"

#include <cstddef>
#include "securec.h"
#include "runtime/rt.h"
#include "utils/math_utils.h"
#include "error_codes_inner.h"
#include "aicpu/dvpp/dvpp_def.h"
#include "toolchain/profiling_manager.h"
#include "toolchain/resource_statistics.h"
#include "aicpu/common/aicpu_task_struct.h"
#include "single_op/dvpp/common/dvpp_util.h"

namespace {
    constexpr uint32_t VENC_NO_INIT = 0U;
    constexpr uint32_t VENC_SYSTEM_MODE = 1U;
    constexpr uint32_t VENC_USER_MODE = 2U;
    constexpr uint8_t SEND_FRAME_EOS = 1U;
}

namespace acl {
    namespace dvpp {
    aclvencChannelDesc *VideoProcessor::CreateVencChannelDescOnHost() const
    {
        ACL_LOG_INFO("CreateVencChannelDescOnHost begin.");
        aclvencChannelDesc *aclChannelDesc = nullptr;
        // alloc host memory
        const size_t aclChannelDescSize = CalAclDvppStructSize(aclChannelDesc);
        ACL_REQUIRES_POSITIVE_RET_NULL(aclChannelDescSize);
        const size_t pageSize = mmGetPageSize();
        void *hostAddr = mmAlignMalloc(aclChannelDescSize, static_cast<size_t>(pageSize));
        if (hostAddr == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][ChannelDesc]malloc memory failed. size is %zu.", aclChannelDescSize);
            return nullptr;
        }

        // create aclvencChannelDesc in host addr
        aclChannelDesc = new (hostAddr)aclvencChannelDesc;
        if ((aclChannelDesc == nullptr) || (aclChannelDesc->vencDesc.extendInfo == nullptr)) {
            ACL_LOG_INNER_ERROR("create aclvencChannelDesc with function new failed");
            ACL_ALIGN_FREE(hostAddr);
            return nullptr;
        }
        const auto err = memset_s(aclChannelDesc->vencDesc.extendInfo, acl::dvpp::VENC_CHANNEL_DESC_TLV_LEN,
                                  0, acl::dvpp::VENC_CHANNEL_DESC_TLV_LEN);
        if (err != EOK) {
            ACL_LOG_INNER_ERROR("[Set][Mem]set vencDesc extendInfo to 0 failed, dstLen = %u, srclen = %u, "
                                "result = %d.", aclChannelDesc->vencDesc.len, aclChannelDesc->vencDesc.len, err);
            ACL_ALIGN_FREE(hostAddr);
            return nullptr;
        }

        // malloc device memory for vencChannelDesc
        void *devPtr = nullptr;
        const size_t size = CalAclDvppStructSize(&aclChannelDesc->vencDesc);
        constexpr uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        const rtError_t ret = rtMalloc(&devPtr, size, flags, acl::ACL_MODE_ID_U16);
        if (ret != RT_ERROR_NONE) {
            ACL_LOG_INNER_ERROR("malloc device memory for acl venc channel desc failed, runtime errorCode = %d", ret);
            ACL_ALIGN_FREE(hostAddr);
            return nullptr;
        }

        // set data buffer
        aclChannelDesc->dataBuffer.data = devPtr;
        aclChannelDesc->dataBuffer.length = size;
        ACL_LOG_INFO("CreateVencChannelDescOnHost success.");
        return aclChannelDesc;
    }

    aclvencChannelDesc *VideoProcessor::CreateVencChannelDescOnDevice() const
    {
        ACL_LOG_INFO("CreateVencChannelDescOnDevice begin.");
        aclvencChannelDesc *aclChannelDesc = nullptr;
        // alloc device memory
        void *devAddr = nullptr;
        const size_t aclChannelDescSize = CalAclDvppStructSize(aclChannelDesc);
        constexpr uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        const rtError_t rtErr = rtMalloc(&devAddr, static_cast<uint64_t>(aclChannelDescSize), flags,
                                         acl::ACL_MODE_ID_U16);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]alloc device memory failed, size = %zu, runtime errorCode = %d",
                               aclChannelDescSize, rtErr);
            return nullptr;
        }

        // create aclvencChannelDesc in device addr
        aclChannelDesc = new (devAddr)aclvencChannelDesc;
        if ((aclChannelDesc == nullptr) || (aclChannelDesc->vencDesc.extendInfo == nullptr)) {
            ACL_LOG_INNER_ERROR("[Create][ChannelDesc]create aclvencChannelDesc with function new failed");
            (void) rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }
        const auto err = memset_s(aclChannelDesc->vencDesc.extendInfo, acl::dvpp::VENC_CHANNEL_DESC_TLV_LEN,
                                  0, acl::dvpp::VENC_CHANNEL_DESC_TLV_LEN);
        if (err != EOK) {
            ACL_LOG_INNER_ERROR("[Set][Mem]set vencDesc extendInfo to 0 failed, dstLen = %u, srclen = %u, "
                                "result = %d.", aclChannelDesc->vencDesc.len, aclChannelDesc->vencDesc.len, err);
            (void) rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }

        // set data buffer
        const auto offset = reinterpret_cast<uintptr_t>(&(reinterpret_cast<aclvencChannelDesc *>(0)->vencDesc));
        aclChannelDesc->dataBuffer.data = reinterpret_cast<aicpu::dvpp::DvppVencDesc *>(
                reinterpret_cast<uintptr_t>(devAddr) + offset);
        aclChannelDesc->dataBuffer.length = CalAclDvppStructSize(&aclChannelDesc->vencDesc);
        ACL_LOG_INFO("CreateVencChannelDescOnDevice success.");
        return aclChannelDesc;
    }

    aclvencChannelDesc *VideoProcessor::aclvencCreateChannelDesc() const
    {
        ACL_LOG_INFO("aclvencCreateChannelDesc begin.");
        // alloc device men for outBuffer
        void *outData = nullptr;
        constexpr uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        const rtError_t rtErr = rtMalloc(&outData, acl::dvpp::MAX_VENC_OUTPUT_BUFFER_SIZE, flags,
                                         acl::ACL_MODE_ID_U16);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]alloc device memory failed, size=%zu, runtime errorCode = %d",
                               acl::dvpp::MAX_VENC_OUTPUT_BUFFER_SIZE, rtErr);
            return nullptr;
        }

        aclvencChannelDesc *aclChannelDesc = nullptr;
        switch (aclRunMode_) {
            case ACL_HOST: {
                aclChannelDesc = CreateVencChannelDescOnHost();
                break;
            }
            case ACL_DEVICE: {
                aclChannelDesc = CreateVencChannelDescOnDevice();
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Check][RunMode]unkown acl run mode %d.", aclRunMode_);
            }
        }

        if (aclChannelDesc == nullptr) {
            (void) rtFree(outData);
            outData = nullptr;
            return nullptr;
        }
        aclChannelDesc->bufAddr = reinterpret_cast<uintptr_t>(outData);
        aclChannelDesc->bufSize = acl::dvpp::MAX_VENC_OUTPUT_BUFFER_SIZE;
        aclChannelDesc->vencDesc.bufAddr = aclChannelDesc->bufAddr;
        aclChannelDesc->vencDesc.bufSize = aclChannelDesc->bufSize;
        ACL_LOG_INFO("aclvencCreateChannelDesc success.");
        return aclChannelDesc;
    }

    aclError VideoProcessor::aclvencDestroyChannelDesc(aclvencChannelDesc *vencChannelDesc) const
    {
        if (vencChannelDesc == nullptr) {
            return ACL_SUCCESS;
        }

        if (vencChannelDesc->isChannelAvailable) {
            ACL_LOG_ERROR("Venc channel should be destroyed first before running aclvencDestroyChannelDesc");
            return ACL_ERROR_RELATIVE_RESOURCE_NOT_CLEARED;
        }

        {
            const std::unique_lock<std::mutex> locker{vencChannelDesc->mutexForTLVMap};
            vencChannelDesc->tlvParamMap.clear();
        }
        void *outData = reinterpret_cast<void *>(static_cast<uintptr_t>(vencChannelDesc->bufAddr));
        if (outData != nullptr) {
            const rtError_t rtErr = rtFree(outData);
            if (rtErr != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Check][RunMode]free device mem failed, runtime errorCode = %d",
                                   static_cast<int32_t>(rtErr));
            }
            outData = nullptr;
            vencChannelDesc->bufAddr = 0U;
        }

        switch (aclRunMode_) {
            case ACL_HOST: {
                FreeDeviceBuffer(vencChannelDesc->dataBuffer);
                ACL_ALIGN_FREE(vencChannelDesc);
                break;
            }
            case ACL_DEVICE: {
                FreeDeviceAddr(static_cast<void *>(vencChannelDesc));
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Destroy][ChannelDesc]venc destroy channel desc failed, "
                                    "unkown acl run mode %d.", aclRunMode_);
                return ACL_ERROR_INTERNAL_ERROR;
            }
        }
        return ACL_SUCCESS;
    }

    aclvencFrameConfig *VideoProcessor::aclvencCreateFrameConfig() const
    {
        ACL_LOG_INFO("start to execute aclvencCreateFrameConfig");
        aclvencFrameConfig *frameConfig = nullptr;
        // malloc memory
        const size_t aclVencFrameConfigSize = CalAclDvppStructSize(frameConfig);
        ACL_REQUIRES_POSITIVE_RET_NULL(aclVencFrameConfigSize);
        void *addr = malloc(aclVencFrameConfigSize);
        if (addr == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][Mem]malloc memory failed. size is %zu.", aclVencFrameConfigSize);
            return nullptr;
        }

        // create aclvencFrameConfig in memory
        frameConfig = new (addr)aclvencFrameConfig();
        if (frameConfig == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][FrameConfig]new aclvencFrameConfig failed");
            ACL_FREE(addr);
            return nullptr;
        }
        return frameConfig;
    }

    aclError VideoProcessor::aclvencDestroyFrameConfig(aclvencFrameConfig *vencFrameConfig) const
    {
        ACL_FREE(vencFrameConfig);
        return ACL_SUCCESS;
    }

    void VideoProcessor::DestroyVencAllNotify(aclvencChannelDesc *const channelDesc) const
    {
        if (channelDesc->sendFrameNotify != nullptr) {
            const rtError_t rtRet = rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->sendFrameNotify));
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Notify]fail to destroy sendFrameNotify, runtime errorCode = %d", rtRet);
            }
            channelDesc->sendFrameNotify = nullptr;
        }

        if (channelDesc->getFrameNotify != nullptr) {
            const rtError_t rtRet = rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->getFrameNotify));
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Notify]fail to destroy getFrameNotify, runtime errorCode = %d", rtRet);
            }
            channelDesc->getFrameNotify = nullptr;
        }
    }

    void VideoProcessor::DestroyVencAllEvent(aclvencChannelDesc *const channelDesc) const
    {
        if (channelDesc->sendFrameNotify != nullptr) {
            const rtError_t rtRetVal = rtEventDestroy(static_cast<rtEvent_t>(channelDesc->sendFrameNotify));
            if (rtRetVal != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Event]fail to destroy sendFrameNotify, runtime errorCode = %d",
                                   rtRetVal);
            }
            channelDesc->sendFrameNotify = nullptr;
        }

        if (channelDesc->getFrameNotify != nullptr) {
            const rtError_t rtRetVal = rtEventDestroy(static_cast<rtEvent_t>(channelDesc->getFrameNotify));
            if (rtRetVal != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Event]fail to destroy getFrameNotify, runtime errorCode = %d", rtRetVal);
            }
            channelDesc->getFrameNotify = nullptr;
        }
    }

    /**
     * destroy all notify and stream for venc channel.
     * @param channelDesc[in] venc channel desc
     * @return void
     */
    void VideoProcessor::DestroyVencAllNotifyAndStream(aclvencChannelDesc *const channelDesc) const
    {
        ACL_LOG_DEBUG("begin to destroy all notify and stream.");
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("[Check][ChannelDesc]venc channel desc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                                                              argList, argVal, 1U);
            return;
        }

        if (channelDesc->vencWaitTaskType == NOTIFY_TASK) {
            DestroyVencAllNotify(channelDesc);
        } else {
            DestroyVencAllEvent(channelDesc);
        }

        if (channelDesc->sendFrameStream != nullptr) {
            const rtError_t rtRet = rtStreamDestroy(channelDesc->sendFrameStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Stream]fail to destroy sendFrameStream, runtime errorCode = %d", rtRet);
            }
            channelDesc->sendFrameStream = nullptr;
        }

        if (channelDesc->getFrameStream != nullptr) {
            const rtError_t rtRet = rtStreamDestroy(channelDesc->getFrameStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Stream]fail to destroy getFrameStream, runtime errorCode = %d", rtRet);
            }
            channelDesc->getFrameStream = nullptr;
        }
        ACL_LOG_DEBUG("success to destroy all notify and stream.");
    }

    aclError VideoProcessor::CreateNotifyForVencChannel(aclvencChannelDesc *const channelDesc) const
    {
        // get deviceId
        int32_t deviceId = 0;
        rtError_t rtRet = rtGetDevice(&deviceId);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Get][Device]fail to get deviceId when create venc channel, errorCode = %d", rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        // create notify for send frame
        rtNotify_t sendFrameNotify = nullptr;
        rtRet = rtNotifyCreate(deviceId, &sendFrameNotify);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Notify]fail to create sendFrameNotify, runtime errorCode = %d", rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->sendFrameNotify = static_cast<void *>(sendFrameNotify);

        // create notify for get frame
        rtNotify_t getFrameNotify = nullptr;
        rtRet = rtNotifyCreate(deviceId, &getFrameNotify);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Notify]fail to create getFrameNotify, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->getFrameNotify = static_cast<void *>(getFrameNotify);

        // get notifyId for send frame
        uint32_t sendFrameNotifyId = 0U;
        rtRet = rtGetNotifyID(sendFrameNotify, &sendFrameNotifyId);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Get][NotifyID]fail to get sendFrameNotifyId, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->vencDesc.sendFrameNotifyId = sendFrameNotifyId;
        ACL_LOG_INFO("venc channel rtGetNotifyID success, send notify id:%u", sendFrameNotifyId);

        // get notifyId for get frame
        uint32_t getFrameNotifyId = 0U;
        rtRet = rtGetNotifyID(getFrameNotify, &getFrameNotifyId);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Get][NotifyID]fail to get getFrameNotifyId, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->vencDesc.getFrameNotifyId = getFrameNotifyId;
        ACL_LOG_INFO("venc channel rtGetNotifyID success, get notify id:%u", getFrameNotifyId);

        return ACL_SUCCESS;
    }

    aclError VideoProcessor::CreateEventForVencChannel(aclvencChannelDesc *const channelDesc) const
    {
        // create event for send frame
        rtEvent_t sendFrameEvent = nullptr;
        rtError_t rtRet = rtEventCreateWithFlag(&sendFrameEvent, RT_EVENT_WITH_FLAG);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Event]fail to create sendFrameEvent, runtime errorCode = %d", rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->sendFrameNotify = static_cast<void *>(sendFrameEvent);

        // create event for get frame
        rtEvent_t getFrameEvent = nullptr;
        rtRet = rtEventCreateWithFlag(&getFrameEvent, RT_EVENT_WITH_FLAG);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Event]fail to create getFrameEvent, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->getFrameNotify = static_cast<void *>(getFrameEvent);

        // get eventId for send frame
        uint32_t sendFrameEventId = 0U;
        rtRet = rtGetEventID(sendFrameEvent, &sendFrameEventId);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Get][Event]fail to get sendFrameEventId, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        ACL_LOG_INFO("sendFrameEventId is %u", sendFrameEventId);
        channelDesc->vencDesc.sendFrameNotifyId = sendFrameEventId;

        // get eventId for get frame
        uint32_t getFrameEventId = 0U;
        rtRet = rtGetEventID(getFrameEvent, &getFrameEventId);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Get][EventID]fail to get getFrameEventId, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        ACL_LOG_INFO("getFrameEventId is %u", getFrameEventId);
        channelDesc->vencDesc.getFrameNotifyId = getFrameEventId;

        return ACL_SUCCESS;
    }

    /**
     * create and record all notify and stream for venc.
     * @param channelDesc venc channel desc
     * @return ACL_SUCCESS for success, other for failed
     */
    aclError VideoProcessor::CreateNotifyAndStremForVencChannel(aclvencChannelDesc *const channelDesc)
    {
        // Verify the validity of the parameters
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("[Check][ChannelDesc]venc channel desc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                                                              argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }

        aclError aclRet;
        if (channelDesc->vencWaitTaskType == NOTIFY_TASK) {
            aclRet = CreateNotifyForVencChannel(channelDesc);
            if (aclRet != ACL_SUCCESS) {
                return aclRet;
            }
        } else {
            aclRet = CreateEventForVencChannel(channelDesc);
            if (aclRet != ACL_SUCCESS) {
                return aclRet;
            }
        }

        // create stream for send frame
        rtStream_t sendFrameStream = nullptr;
        rtError_t rtRet = rtStreamCreate(&sendFrameStream, static_cast<int32_t>(RT_STREAM_PRIORITY_DEFAULT));
        if (rtRet != ACL_SUCCESS) {
            ACL_LOG_CALL_ERROR("[Create][Stream]fail to create sendFrameStream, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->sendFrameStream = sendFrameStream;

        // create stream for get frame
        rtStream_t getFrameStream = nullptr;
        rtRet = rtStreamCreate(&getFrameStream, static_cast<int32_t>(RT_STREAM_PRIORITY_DEFAULT));
        if (rtRet != ACL_SUCCESS) {
            ACL_LOG_CALL_ERROR("[Create][Stream]fail to create getFrameStream, errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        channelDesc->getFrameStream = getFrameStream;

        return ACL_SUCCESS;
    }

    /**
 * choose memroy mode.
 * @param channelDesc venc channel desc
 * @param output output dvpp stream desc
 * @return ACL_SUCCESS for success, other for failed
 */
    aclError VideoProcessor::ChooseMemMode(aclvencChannelDesc *const channelDesc, acldvppStreamDesc *&output) const
    {
        if (channelDesc->outputMemMode == VENC_NO_INIT) {
            if (output == nullptr) {
                channelDesc->outputMemMode = VENC_SYSTEM_MODE;
            } else {
                channelDesc->outputMemMode = VENC_USER_MODE;
            }
        }

        if (channelDesc->outputMemMode != VENC_SYSTEM_MODE) {
            ACL_LOG_INNER_ERROR("[Check][MemMode]venc user mode:%d is not supported and output "
                                "should be null.", VENC_USER_MODE);
            return ACL_ERROR_INVALID_PARAM;
        }

        if (output != nullptr) {
            ACL_LOG_INFO("output memery mode is system mode, but output isn't null.");
            output = nullptr;
        }

        output = acldvppCreateStreamDesc();
        ACL_REQUIRES_NOT_NULL(output);
        if (output->dataBuffer.data == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][DataBuffer]output dvpp stream desc dataBuffer data is null.");
            (void)acldvppDestroyStreamDesc(output);
            return ACL_ERROR_RT_FAILURE;
        }
        output->dvppStreamDesc.data = channelDesc->bufAddr;
        output->dvppStreamDesc.size = channelDesc->bufSize;

        // memcpy data to device
        if (aclRunMode_ == ACL_HOST) {
            const aclError ret = MemcpyDataToDevice(output);
            if (ret != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][Mem]MemcpyDataToDevice failed, errorCode = %d.", ret);
                (void)acldvppDestroyStreamDesc(output);
                return ret;
            }
        }

        ACL_LOG_INFO("choose memory mode successfully.");
        return ACL_SUCCESS;
    }

    /**
     * dvpp venc launch send frame task.
     * @param channelDesc venc channel desc
     * @param inputPicDesc input picture desc
     * @param outputStreamDesc output stream desc
     * @param config dvpp frame config
     * @return ACL_SUCCESS for ok, others for fail
     */
    aclError VideoProcessor::LaunchVencSendFrameTask(const aclvencChannelDesc *const channelDesc,
                                                     const acldvppPicDesc *const inputPicDesc,
                                                     const acldvppStreamDesc *const outputStreamDesc,
                                                     const aclvencFrameConfig *const config) const
    {
        constexpr uint32_t ioAddrNum = 3U;
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) +
                                CalDevDvppStructRealUsedSize(&config->vencFrameConfig);
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        int32_t i = 0;
        ioAddr[i] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        const bool eos = config->vencFrameConfig.eos;
        if (eos) {
            ++i;
            ioAddr[i] = 0U;
            ++i;
            ioAddr[i] = 0U;
        } else {
            ++i;
            ACL_REQUIRES_NOT_NULL(inputPicDesc);
            ioAddr[i] = reinterpret_cast<uintptr_t>(inputPicDesc->dataBuffer.data);
            ++i;
            ACL_REQUIRES_NOT_NULL(outputStreamDesc);
            ioAddr[i] = reinterpret_cast<uintptr_t>(outputStreamDesc->dataBuffer.data);
        }
        constexpr size_t configOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        const auto memcpyRet = memcpy_s(args.get() + configOffset, (argsSize - configOffset),
                                        &(config->vencFrameConfig), CalDevDvppStructRealUsedSize(&config->vencFrameConfig));
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Frame]copy venc frame config to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        ACL_LOG_INFO("begin to send frame to device, eos = %d.", static_cast<int32_t>(eos));
        rtArgsEx_t argsInfo = {};
        argsInfo.args = args.get();
        argsInfo.argsSize = static_cast<uint32_t>(argsSize);
        const rtError_t rtRet = rtCpuKernelLaunchWithFlag(acl::dvpp::DVPP_KERNELS_SONAME,
                                                          acl::dvpp::DVPP_KERNELNAME_VENC_SEND_FRAME, 1U, &argsInfo, nullptr,
                                                          channelDesc->sendFrameStream, RT_KERNEL_DEFAULT);
        ACL_LOG_INFO("end to send frame to device.");
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Launch][Task]venc send frame task call rtCpuKernelLaunchWithFlag failed, "
                               "runtime errorCode = %d.", rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        return ACL_SUCCESS;
    }


    /**
     * dvpp venc launch release frame task.
     * @param channelDesc venc channel desc
     * @return ACL_SUCCESS for ok, others for fail
     */
    aclError VideoProcessor::LaunchReleaseFrameTask(const aclvencChannelDesc *const channelDesc) const
    {
        constexpr uint32_t ioAddrNum = 1U;

        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
                                                            (ioAddrNum * sizeof(uint64_t)) + sizeof(uint8_t));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));

        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);

        constexpr uint32_t offset = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
                                                          (ioAddrNum * sizeof(uint64_t)));
        const auto memcpyRet = memcpy_s(args.get() + offset,
                                        argsSize - offset,
                                        &(channelDesc->outputMemMode),
                                        sizeof(uint8_t));
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Mem]copy output memory mode to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }
        rtArgsEx_t argsInfo = {};
        argsInfo.args = args.get();
        argsInfo.argsSize = argsSize;
        const rtError_t rtRet = rtCpuKernelLaunchWithFlag(acl::dvpp::DVPP_KERNELS_SONAME,
                                                          acl::dvpp::DVPP_KERNELNAME_VENC_RELEASE_FRAME,
                                                          1U, // blockDim default 1
                                                          &argsInfo,
                                                          nullptr, // no need smDesc
                                                          channelDesc->getFrameStream,
                                                          RT_KERNEL_DEFAULT);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Launch][Task]release venc frame task call rtCpuKernelLaunchWithFlag failed, "
                               "runtime errorCode = %d.", rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        return ACL_SUCCESS;
    }

    /**
     * get venc frame callback function for runtime.
     * @param callbackData callback user data
     * @return void
     */
    void VideoProcessor::GetVencFrameCallback(void *const callbackData)
    {
        ACL_LOG_INFO("start to execute GetVencFrameCallback");
        const auto addr = reinterpret_cast<uintptr_t>(callbackData);
        const auto info = aicpu::dvpp::CallbackInfoManager<aicpu::dvpp::VencCallbackInfoPtr>::Instance().Take(addr);
        if (info == nullptr) {
            ACL_LOG_CALL_ERROR("[Check][Info]GetVencFrameCallback callbackData = %p, "
                               "but no info found in CallbackInfoManager.", callbackData);
            return;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy outputPicDesc to host
            constexpr size_t size = sizeof(aicpu::dvpp::DvppStreamDesc);
            const aclError ret = rtMemcpy(&(info->outputStreamDesc->dvppStreamDesc), size,
                                          info->outputStreamDesc->dataBuffer.data, size,
                                          RT_MEMCPY_DEVICE_TO_HOST);
            if (ret != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][Mem]memcpy output stream desc to host memory failed, "
                                    "size = %zu, errorCode = %d", size, ret);
                if (info->outputMemMode == VENC_SYSTEM_MODE) {
                    (void)acldvppDestroyStreamDesc(info->outputStreamDesc);
                }
                return;
            }

            ACL_LOG_INFO("rtMemcpy success, timestamp:%lu, size:%u, format:%u, eos:%d, retCode:%u.",
                         info->outputStreamDesc->dvppStreamDesc.timestamp,
                         info->outputStreamDesc->dvppStreamDesc.size,
                         info->outputStreamDesc->dvppStreamDesc.format,
                         static_cast<int32_t>(info->outputStreamDesc->dvppStreamDesc.eos),
                         info->outputStreamDesc->dvppStreamDesc.retCode);
        }

        // check user callback func
        if (info->callbackFunc == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][Callback]call back func is null!");
            if (info->outputMemMode == VENC_SYSTEM_MODE) {
                (void)acldvppDestroyStreamDesc(info->outputStreamDesc);
            }
            return;
        }

        // call user callback func
        const aclvencCallback callbackFunc = info->callbackFunc;
        (*callbackFunc)(info->inputPicDesc, info->outputStreamDesc, info->callbackData);

        if (info->outputMemMode == VENC_SYSTEM_MODE) {
            (void)acldvppDestroyStreamDesc(info->outputStreamDesc);
        }

        ACL_LOG_INFO("successfully execute GetVencFrameCallback");
        return;
    }

    /**
     * dvpp venc launch send eos frame task.
     * @param channelDesc venc channel desc
     * @param config dvpp frame config
     * @return ACL_SUCCESS for ok, others for fail
     */
    aclError VideoProcessor::aclvencSendEosFrame(aclvencChannelDesc *const channelDesc,
                                                 aclvencFrameConfig *const config) const
    {
        // launch send frame task to send frame stream
        const aclError sendFrameRet = LaunchVencSendFrameTask(channelDesc, nullptr, nullptr, config);
        if (sendFrameRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch send frame task failed, errorCode = %d", sendFrameRet);
            return sendFrameRet;
        }

        // launch wait task to send frame stream
        const rtError_t sendFrameWaitRet = rtNotifyWait(static_cast<rtNotify_t>(channelDesc->sendFrameNotify),
                                                        channelDesc->sendFrameStream);
        if (sendFrameWaitRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Wait][Notify]wait for a notify to send frame stream failed, "
                               "runtime errorCode = %d", sendFrameWaitRet);
            return ACL_GET_ERRCODE_RTS(sendFrameWaitRet);
        }

        // if eos is true, no task in get frame stream
        ACL_LOG_INFO("rtStreamSynchronize send frame begin.");
        const rtError_t streamSynRet = rtStreamSynchronize(channelDesc->sendFrameStream);
        if (streamSynRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]fail to synchronize sendFrameStream, runtime errorCode = %d",
                               streamSynRet);
            (void) rtStreamSynchronize(channelDesc->getFrameStream);
            return ACL_GET_ERRCODE_RTS(streamSynRet);
        }
        ACL_LOG_INFO("rtStreamSynchronize send frame end.");

        // synchronize getFrameStream
        ACL_LOG_INFO("rtStreamSynchronize get frame begin.");
        const rtError_t rtRet = rtStreamSynchronize(channelDesc->getFrameStream);
        if (rtRet != ACL_SUCCESS) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]fail to synchronize getFrameStream, errorCode = %d", rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        ACL_LOG_INFO("rtStreamSynchronize get frame end.");
        return ACL_SUCCESS;
    }

    /**
     * Venc check parameter
     * @param channelDesc venc channel desc
     * @param input input picture desc
     * @return ACL_SUCCESS for ok, others for fail
     */
    aclError VideoProcessor::CheckVencParameter(const aclvencChannelDesc *const channelDesc,
                                                const acldvppPicDesc *const input) const
    {
        // if the verification logic is modified, acl and dvpp must perform the modification at the same time
        uint32_t oneFrameSize = 0U;
        ACL_CHECK_ASSIGN_UINT32_MULTI(channelDesc->vencDesc.picWidth, channelDesc->vencDesc.picHeight, oneFrameSize);
        // size of nv12 or nv21 image is equal to width  * height * 3 / 2
        ACL_CHECK_ASSIGN_UINT32_MULTI(oneFrameSize, 3U, oneFrameSize);
        oneFrameSize = oneFrameSize / 2U;
        // picture size by user setting must be in range [oneFrameSize, oneFrameSize * 2)
        if ((input->dvppPicDesc.size < oneFrameSize) || (input->dvppPicDesc.size >= (oneFrameSize * 2U))) {
            ACL_LOG_INNER_ERROR("[Check][Params]invalid picture size %u by user setting, it must be in range [%u, %u)",
                                input->dvppPicDesc.size, oneFrameSize, oneFrameSize * 2U);
            return ACL_ERROR_INVALID_PARAM;
        }

        return ACL_SUCCESS;
    }

    /**
     * dvpp venc launch send normal frame task.
     * @param channelDesc venc channel desc
     * @param input input picture desc
     * @param config dvpp frame config
     * @param userdata user callback function
     * @return ACL_SUCCESS for ok, others for fail
     */
    aclError VideoProcessor::aclvencSendNomalFrame(aclvencChannelDesc *const channelDesc,
                                                   acldvppPicDesc *input,
                                                   void *const reserve,
                                                   aclvencFrameConfig *const config,
                                                   void *userdata)

    {
        (void)(reserve);
        ACL_REQUIRES_NOT_NULL(input);
        ACL_REQUIRES_NOT_NULL(input->dataBuffer.data);

        aclError ret = CheckVencParameter(channelDesc, input);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][VencParameter]check venc parameter failed, errorCode = %d", ret);
            return ret;
        }

        // choose memory mode
        acldvppStreamDesc *output = nullptr;
        ret = ChooseMemMode(channelDesc, output);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Choose][MemMode]choose memory mode failed, errorCode = %d", ret);
            return ret;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy input pic desc to device
            constexpr size_t size = sizeof(aicpu::dvpp::DvppPicDesc);
            const rtError_t memcpyRet = rtMemcpy(input->dataBuffer.data, input->dataBuffer.length,
                                                 static_cast<const void *>(&input->dvppPicDesc), size, RT_MEMCPY_HOST_TO_DEVICE);
            if (memcpyRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Copy][Mem]memcpy input pic desc to device memory failed, "
                                   "size = %zu, runtime errorCode = %d", size, memcpyRet);
                (void)acldvppDestroyStreamDesc(output);
                return ACL_GET_ERRCODE_RTS(memcpyRet);
            }
        }

        // launch send frame task to send frame stream
        const aclError sendFrameRet = LaunchVencSendFrameTask(channelDesc, input, output, config);
        if (sendFrameRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch send frame task failed, errorCode = %d", sendFrameRet);
            (void)acldvppDestroyStreamDesc(output);
            return sendFrameRet;
        }

        // launch wait task to send frame stream
        const rtError_t sendFrameWaitRet = rtNotifyWait(static_cast<rtNotify_t>(channelDesc->sendFrameNotify),
                                                        channelDesc->sendFrameStream);
        if (sendFrameWaitRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Wait][Notify]wait for a notify to send frame stream failed, "
                               "runtime errorCode = %d", sendFrameWaitRet);
            (void)acldvppDestroyStreamDesc(output);
            return ACL_GET_ERRCODE_RTS(sendFrameWaitRet);
        }

        // launch wait task to get frame stream
        const rtError_t getFrameWaitRet = rtNotifyWait(static_cast<rtNotify_t>(channelDesc->getFrameNotify),
                                                       channelDesc->getFrameStream);
        if (getFrameWaitRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Wait][Notify]wait for a notify to get frame stream failed, "
                               "runtime errorCode = %d", getFrameWaitRet);
            (void)acldvppDestroyStreamDesc(output);
            return ACL_GET_ERRCODE_RTS(getFrameWaitRet);
        }

        // create callback info
        aicpu::dvpp::VencCallbackInfoPtr callbackInfoPtr;
        try {
            callbackInfoPtr = std::make_shared<aicpu::dvpp::VencGetFrameCallbackInfo>(
                    channelDesc->callback, input, output, channelDesc->outputMemMode, userdata);
        } catch (std::bad_alloc &) {
            ACL_LOG_INNER_ERROR("[Make][Shared]Make shared for get frame callback info failed.");
            (void)acldvppDestroyStreamDesc(output);
            return ACL_ERROR_BAD_ALLOC;
        }
        // save callback info
        const auto addr = reinterpret_cast<uintptr_t>(callbackInfoPtr.get());
        // Insert return code is always true, no need to check
        (void)aicpu::dvpp::CallbackInfoManager<aicpu::dvpp::VencCallbackInfoPtr>::
        Instance().Insert(addr, callbackInfoPtr);
        // launch callback task to get frame stream
        const rtError_t callbackRet = rtCallbackLaunch(&GetVencFrameCallback,
                                                       callbackInfoPtr.get(),
                                                       channelDesc->getFrameStream, true);
        if (callbackRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Launch][Task]launch callback to get frame stream failed, "
                               "runtime errorCode = %d", callbackRet);
            (void)aicpu::dvpp::CallbackInfoManager<aicpu::dvpp::VencCallbackInfoPtr>::Instance().Erase(addr);
            return ACL_GET_ERRCODE_RTS(callbackRet);
        }

        // launch release frame task to get frame stream
        const aclError releaseFrameRet = LaunchReleaseFrameTask(channelDesc);
        if (releaseFrameRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch release frame task failed, errorCode = %d", releaseFrameRet);
            return releaseFrameRet;
        }

        // streamSynchronize send frame stream
        const rtError_t streamSynRet = rtStreamSynchronize(channelDesc->sendFrameStream);
        if (streamSynRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]fail to synchronize sendFrameStream, runtime errorCode = %d",
                               streamSynRet);
            (void)aicpu::dvpp::CallbackInfoManager<aicpu::dvpp::VencCallbackInfoPtr>::Instance().Erase(addr);
            return ACL_GET_ERRCODE_RTS(streamSynRet);
        }

        return ACL_SUCCESS;
    }

    /**
     * send eos for venc.
     * @param channelDesc venc channel desc
     * @return ACL_SUCCESS for success, other for failed
     */
    aclError VideoProcessor::SendEosForVenc(aclvencChannelDesc *const channelDesc) const
    {
        // create input config desc
        aclvencFrameConfig *const config = aclvencCreateFrameConfig();
        if (config == nullptr) {
            ACL_LOG_INNER_ERROR("[Send][Eos]fail to create dvpp config desc for eos.");
            return ACL_ERROR_BAD_ALLOC;
        }

        // set eos
        aclError ret = aclvencSetFrameConfigEos(config, SEND_FRAME_EOS);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Set][FrameConfig]fail to set eos, errorCode = %d", ret);
            (void) aclvencDestroyFrameConfig(config);
            return ret;
        }

        // send eos and sychronize
        ret = aclvencSendEosFrame(channelDesc, config);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Send][EosFrame]fail to send eos, errorCode = %d", ret);
            (void) aclvencDestroyFrameConfig(config);
            return ret;
        }

        // destory input stream desc
        ret = aclvencDestroyFrameConfig(config);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Destroy][FrameConfig]fail to destory dvpp config desc for eos, errorCode = %d", ret);
            return ret;
        }
        return ACL_SUCCESS;
    }

    void VideoProcessor::SetVencWaitTaskType(aclvencChannelDesc *const channelDesc) const
    {
        channelDesc->vencWaitTaskType = NOTIFY_TASK;
        ACL_LOG_INFO("venc wait task type is notify");
    }

    aclError VideoProcessor::SetVencParamToVencChannel(aclvencChannelDesc *const channelDesc) const
    {
        uint32_t offset = 0U;
        const std::unique_lock<std::mutex> locker{channelDesc->mutexForTLVMap};
        for (auto &it : channelDesc->tlvParamMap) {
            ACL_REQUIRES_NOT_NULL(it.second.value.get());
            uint32_t tmpOffset = offset;
            ACL_CHECK_ASSIGN_UINT32T_ADD(tmpOffset, static_cast<uint32_t>(it.second.valueLen), tmpOffset);
            if (tmpOffset > VENC_CHANNEL_DESC_TLV_LEN) {
                ACL_LOG_INNER_ERROR("[Check][Offset] offset %u can not be larger than %u",
                                    tmpOffset, VENC_CHANNEL_DESC_TLV_LEN);
                return ACL_ERROR_FAILURE;
            }
            const auto ret = memcpy_s(channelDesc->vencDesc.extendInfo + offset, it.second.valueLen,
                                      it.second.value.get(), it.second.valueLen);
            if (ret != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][Mem]call memcpy_s failed, result = %d, srcLen = %zu, dstLen = %zu", ret,
                                    it.second.valueLen, it.second.valueLen);
                return ACL_ERROR_FAILURE;
            }
            offset += static_cast<uint32_t>(it.second.valueLen);
        }
        channelDesc->vencDesc.len = offset;

        return ACL_SUCCESS;
    }

    aclError VideoProcessor::aclvencCreateChannel(aclvencChannelDesc *const channelDesc)
    {
        ACL_LOG_INFO("aclvencCreateChannel begin");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);

        aclError aclRet = SetVencParamToVencChannel(channelDesc);
        if (aclRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Set][VencParam]set venc parameter failed, errorCode = %d", aclRet);
            return aclRet;
        }
        SetVencWaitTaskType(channelDesc);

        // create 2 notify and 2 stream for venc channel desc
        aclRet = CreateNotifyAndStremForVencChannel(channelDesc);
        if (aclRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Create][Notify]create notify and stream for venc channel failed, "
                                "result = %d", aclRet);
            return aclRet;
        }

        // subscribe report
        rtError_t rtRet = rtSubscribeReport(channelDesc->threadId, channelDesc->getFrameStream);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Subscribe][Report]subscribe report failed, runtime errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        aclRet = aclvencMallocOutMemory(channelDesc);
        if (aclRet != ACL_SUCCESS) {
            (void)rtUnSubscribeReport(channelDesc->threadId, channelDesc->getFrameStream);
            DestroyVencAllNotifyAndStream(channelDesc);
            ACL_LOG_INNER_ERROR("[Malloc][Mem]malloc out buffer for venc channel failed, errorCode = %d", aclRet);
            return aclRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // memcpy data to device (both async and sync copy type are OK for this api)
            const size_t size = CalDevDvppStructRealUsedSize(&channelDesc->vencDesc);
            rtRet = rtMemcpyAsync(channelDesc->dataBuffer.data,
                                  channelDesc->dataBuffer.length,
                                  static_cast<const void *>(&channelDesc->vencDesc),
                                  size,
                                  RT_MEMCPY_HOST_TO_DEVICE,
                                  channelDesc->sendFrameStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Copy][Mem]memcpy to device memory failed, dst size = %lu,"
                                   "src size = %zu, runtime errorCode = %d", channelDesc->dataBuffer.length,
                                   size, rtRet);
                (void)rtUnSubscribeReport(channelDesc->threadId, channelDesc->getFrameStream);
                DestroyVencAllNotifyAndStream(channelDesc);
                aclvencFreeOutMemory(channelDesc);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        }

        // create channel have only 2 input
        constexpr uint32_t ioAddrNum = 2U;
        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
                                                            (ioAddrNum * sizeof(uint64_t)));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = (channelDesc->outStreamDesc == nullptr) ? 0U :
                    reinterpret_cast<uintptr_t>(channelDesc->outStreamDesc->dataBuffer.data);

        // launch create channel task
        rtArgsEx_t argsInfo = {};
        argsInfo.args = args.get();
        argsInfo.argsSize = argsSize;
        rtRet = rtCpuKernelLaunchWithFlag(acl::dvpp::DVPP_KERNELS_SONAME,
                                          acl::dvpp::DVPP_KERNELNAME_CREATE_VENC_CHANNEL,
                                          1U,
                                          &argsInfo,
                                          nullptr,
                                          channelDesc->sendFrameStream,
                                          RT_KERNEL_DEFAULT);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Launch][Task]create venc channel call rtCpuKernelLaunchWithFlag failed, "
                               "runtime errorCode = %d", rtRet);
            (void)rtUnSubscribeReport(channelDesc->threadId, channelDesc->getFrameStream);
            DestroyVencAllNotifyAndStream(channelDesc);
            aclvencFreeOutMemory(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        if (aclRunMode_ == ACL_HOST) {
            const size_t size = acl::dvpp::CalAclDvppStructSize(&channelDesc->vencDesc);
            rtRet = rtMemcpyAsync(&channelDesc->vencDesc, size,
                                  static_cast<const void *>(channelDesc->dataBuffer.data),
                                  channelDesc->dataBuffer.length,
                                  RT_MEMCPY_DEVICE_TO_HOST, channelDesc->sendFrameStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Copy][Mem]memcpy to host memory failed, size = %zu, "
                                   "runtime errorCode = %d", size, rtRet);
                (void)rtUnSubscribeReport(channelDesc->threadId, channelDesc->getFrameStream);
                DestroyVencAllNotifyAndStream(channelDesc);
                aclvencFreeOutMemory(channelDesc);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        }

        // stream synchronize
        rtRet = rtStreamSynchronize(channelDesc->sendFrameStream);
        if (rtRet != ACL_SUCCESS) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]fail to synchronize sendFrameStream, errorCode = %d", rtRet);
            (void)rtUnSubscribeReport(channelDesc->threadId, channelDesc->getFrameStream);
            DestroyVencAllNotifyAndStream(channelDesc);
            aclvencFreeOutMemory(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        ACL_LOG_INFO("success to call aclvencCreateChannel, channelId = %u, sendFrameNotifyId = %u, "
                     "getFrameNotifyId = %u, bufAddr = %lu, bufSize = %u.",
                     channelDesc->vencDesc.channelId, channelDesc->vencDesc.sendFrameNotifyId,
                     channelDesc->vencDesc.getFrameNotifyId, channelDesc->bufAddr, channelDesc->bufSize);
        ACL_ADD_APPLY_SUCCESS_COUNT(ACL_STATISTICS_CREATE_DESTROY_VENC_CHANNEL);
        channelDesc->isChannelAvailable = true;
        return ACL_SUCCESS;
    }

    aclError VideoProcessor::aclvencDestroyChannel(aclvencChannelDesc *const channelDesc)
    {
        ACL_LOG_INFO("start to execute aclvencDestroyChannel");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);

        // send eos to send stream to finish decode all frame
        const aclError aclRet = SendEosForVenc(channelDesc);
        if (aclRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Send][Eos]fail to send eos to sendFrameStream, errorCode = %d", aclRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            aclvencFreeOutMemory(channelDesc);
            return aclRet;
        }

        // destroy channel have 1 input
        constexpr uint32_t ioAddrNum = 1U;
        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
                                                            (ioAddrNum * sizeof(uint64_t)));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto cpuParamHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        cpuParamHead->length = argsSize;
        cpuParamHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);

        rtArgsEx_t argsInfo = {};
        argsInfo.args = args.get();
        argsInfo.argsSize = argsSize;
        rtError_t rtRet = rtCpuKernelLaunchWithFlag(acl::dvpp::DVPP_KERNELS_SONAME,
                                                    acl::dvpp::DVPP_KERNELNAME_DESTROY_VENC_CHANNEL, 1U, &argsInfo, nullptr,
                                                    channelDesc->sendFrameStream, RT_KERNEL_DEFAULT);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Venc]destroy venc call rtCpuKernelLaunchWithFlag failed, rtRet %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            aclvencFreeOutMemory(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        rtRet = rtStreamSynchronize(channelDesc->sendFrameStream);
        if (rtRet != ACL_SUCCESS) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]fail to synchronize sendFrameStream, errorCode = %d", rtRet);
            DestroyVencAllNotifyAndStream(channelDesc);
            aclvencFreeOutMemory(channelDesc);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        // releasing the memory after channel is destroyed
        aclvencFreeOutMemory(channelDesc);

        rtRet = rtUnSubscribeReport(channelDesc->threadId, channelDesc->getFrameStream);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Unsub][Report]fail to UnSubscribeReport thread, runtime errorCode = %d", rtRet);
            // no need to return failed, continue to destory resource
        }

        // destory all notify and stream
        DestroyVencAllNotifyAndStream(channelDesc);
        channelDesc->isChannelAvailable = false;
        return ACL_SUCCESS;
    }

    aclError VideoProcessor::aclvencSetChannelDescPicFormat(aclvencChannelDesc *const channelDesc,
                                                            const acldvppPixelFormat picFormat) const
    {
        ACL_LOG_DEBUG("start to execute aclvencSetChannelDescPicFormat");
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("[Check][ChannelDesc]channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"videoProcessor"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                                                              argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        // venc only support 2 format
        if ((picFormat != PIXEL_FORMAT_YUV_SEMIPLANAR_420) &&
            (picFormat != PIXEL_FORMAT_YVU_SEMIPLANAR_420)) {
            ACL_LOG_INNER_ERROR("[Check][PicFormat]input format[%u] is not supported in this version, "
                                "only support nv12 and nv21", static_cast<uint32_t>(picFormat));
            return ACL_ERROR_INVALID_PARAM;
        }

        channelDesc->vencDesc.picFormat = static_cast<uint32_t>(picFormat);
        return ACL_SUCCESS;
    }

    aclError VideoProcessor::aclvencSendFrame(aclvencChannelDesc *const channelDesc, acldvppPicDesc *const input,
                                              void *const reserve, aclvencFrameConfig *const config, void *const userdata)
    {
        ACL_LOG_INFO("start to execute aclvencSendFrame");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        if (!channelDesc->isChannelAvailable) {
            ACL_LOG_ERROR("please execute aclvenccCreateChannel before aclvencSendFrame");
            return ACL_ERROR_INVALID_PARAM;
        }
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(channelDesc->sendFrameStream);
        ACL_REQUIRES_NOT_NULL(channelDesc->getFrameStream);
        ACL_REQUIRES_NOT_NULL(config);

        // if eos is true, frame data with true eos will not be decoded
        if (config->vencFrameConfig.eos) {
            return aclvencSendEosFrame(channelDesc, config);
        } else {
            return aclvencSendNomalFrame(channelDesc, input, reserve, config, userdata);
        }
    }

    /**
 * VENC set buf size for channel desc.
 * @param channelDesc[in|out] channel desc
 * @param bufSize[in] buf size
 * @return ACL_SUCCESS for ok, others for fail
 */
    aclError VideoProcessor::aclvencSetChannelDescBufSize(aclvencChannelDesc *const channelDesc,
                                                          const uint32_t bufSize) const
    {
        (void)(channelDesc);
        (void)(bufSize);
        ACL_LOG_INNER_ERROR("[Unsupport][Feature]Setting bufsize for channel desc is "
                            "not supported in this version. Please check.");
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    /**
     * VENC set buf addr for channel desc.
     * @param channelDesc[in|out] channel desc
     * @param bufAddr[in] buf addr
     * @return ACL_SUCCESS for ok, others for fail
     */
    aclError VideoProcessor::aclvencSetChannelDescBufAddr(aclvencChannelDesc *const channelDesc,
                                                          void *const bufAddr) const
    {
        (void)(channelDesc);
        (void)(bufAddr);
        ACL_LOG_INNER_ERROR("[Unsupport][Feature]Setting bufAddr for channel desc is not "
                            "supported in this version. Please check.");
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    /**
     * Set rc model for venc channel desc.
     * @param channelDesc[IN/OUT] venc channel desc
     * @param rcMode[IN] venc rc mode(VBR=1, CBR=2)
     * @return ACL_SUCCESS for success, other for failure
     */
    aclError VideoProcessor::aclvencSetChannelDescRcMode(aclvencChannelDesc *const channelDesc,
                                                         const uint32_t rcMode) const
    {
        ACL_LOG_INFO("start to execute aclvencSetChannelDescRcMode, rcMode %u", rcMode);
        ACL_REQUIRES_NOT_NULL(channelDesc);
        {
            const std::unique_lock<std::mutex> locker{channelDesc->mutexForTLVMap};
            std::map<acl::VencTLVType, acl::VencChannelDescTLVParam>::const_iterator it =
                    channelDesc->tlvParamMap.find(VENC_RATE_CONTROL);
            if (it == channelDesc->tlvParamMap.cend()) {
                VencChannelDescTLVParam vencTLVParam;
                const std::shared_ptr<aicpu::dvpp::VencRateControl> vencRateControlPtr =
                        std::make_shared<aicpu::dvpp::VencRateControl>();
                ACL_REQUIRES_NOT_NULL(vencRateControlPtr);
                vencRateControlPtr->rcMode = rcMode;
                vencTLVParam.value = static_cast<std::shared_ptr<void>>(vencRateControlPtr);
                vencTLVParam.valueLen = sizeof(aicpu::dvpp::VencRateControl);
                channelDesc->tlvParamMap[VENC_RATE_CONTROL] = vencTLVParam;
            } else {
                aicpu::dvpp::VencRateControl *const vencRateControlPtr =
                        static_cast<aicpu::dvpp::VencRateControl *>(it->second.value.get());
                ACL_REQUIRES_NOT_NULL(vencRateControlPtr);
                vencRateControlPtr->rcMode = rcMode;
            }
        }

        return ACL_SUCCESS;
    }

    /**
     * Set source rate for venc channel desc.
     * @param channelDesc[IN/OUT] venc channel desc
     * @param srcRate[IN] source rate
     * @return ACL_SUCCESS for success, other for failure
     */
    aclError VideoProcessor::aclvencSetChannelDescSrcRate(aclvencChannelDesc *const channelDesc,
                                                          const uint32_t srcRate) const
    {
        ACL_LOG_INFO("start to execute aclvencSetChannelDescSrcRate, srcRate %u", srcRate);
        ACL_REQUIRES_NOT_NULL(channelDesc);

        {
            const std::unique_lock<std::mutex> locker{channelDesc->mutexForTLVMap};
            std::map<acl::VencTLVType, acl::VencChannelDescTLVParam>::const_iterator it =
                    channelDesc->tlvParamMap.find(VENC_RATE_CONTROL);
            if (it == channelDesc->tlvParamMap.cend()) {
                VencChannelDescTLVParam vencTLVParam;
                const std::shared_ptr<aicpu::dvpp::VencRateControl> vencRateControlPtr =
                        std::make_shared<aicpu::dvpp::VencRateControl>();
                ACL_REQUIRES_NOT_NULL(vencRateControlPtr);
                vencRateControlPtr->srcRate = srcRate;
                vencTLVParam.value = static_cast<std::shared_ptr<void>>(vencRateControlPtr);
                vencTLVParam.valueLen = sizeof(aicpu::dvpp::VencRateControl);
                channelDesc->tlvParamMap[VENC_RATE_CONTROL] = vencTLVParam;
            } else {
                aicpu::dvpp::VencRateControl *const vencRateControlPtr =
                        static_cast<aicpu::dvpp::VencRateControl *>(it->second.value.get());
                ACL_REQUIRES_NOT_NULL(vencRateControlPtr);
                vencRateControlPtr->srcRate = srcRate;
            }
        }

        return ACL_SUCCESS;
    }

    /**
     * Set max bit rate for venc channel desc.
     * @param channelDesc[IN/OUT] venc channel desc
     * @param maxBitRate[IN] max bit rate
     * @return ACL_SUCCESS for success, other for failure
     */
    aclError VideoProcessor::aclvencSetChannelDescMaxBitRate(aclvencChannelDesc *const channelDesc,
                                                             const uint32_t maxBitRate) const
    {
        ACL_LOG_INFO("start to execute aclvencSetChannelDescMaxBitRate, maxBitRate %u", maxBitRate);
        ACL_REQUIRES_NOT_NULL(channelDesc);

        {
            const std::unique_lock<std::mutex> locker{channelDesc->mutexForTLVMap};
            std::map<acl::VencTLVType, acl::VencChannelDescTLVParam>::const_iterator it =
                    channelDesc->tlvParamMap.find(VENC_RATE_CONTROL);
            if (it == channelDesc->tlvParamMap.cend()) {
                VencChannelDescTLVParam vencTLVParam;
                const std::shared_ptr<aicpu::dvpp::VencRateControl> vencRateControlPtr =
                        std::make_shared<aicpu::dvpp::VencRateControl>();
                ACL_REQUIRES_NOT_NULL(vencRateControlPtr);
                vencRateControlPtr->maxBitRate = maxBitRate;
                vencTLVParam.value = static_cast<std::shared_ptr<void>>(vencRateControlPtr);
                vencTLVParam.valueLen = sizeof(aicpu::dvpp::VencRateControl);
                channelDesc->tlvParamMap[VENC_RATE_CONTROL] = vencTLVParam;
            } else {
                aicpu::dvpp::VencRateControl *const vencRateControlPtr =
                        static_cast<aicpu::dvpp::VencRateControl *>(it->second.value.get());
                ACL_REQUIRES_NOT_NULL(vencRateControlPtr);
                vencRateControlPtr->maxBitRate = maxBitRate;
            }
        }

        return ACL_SUCCESS;
    }

    /**
     * Set ip proportion for venc channel desc.
     * @param channelDesc[OUT] venc channel desc
     * @param ipProp[IN] I frame and P frame proportion
     * @return ACL_SUCCESS for success, other for failure
     */
    aclError VideoProcessor::aclvencSetChannelDescIPProp(aclvencChannelDesc *const channelDesc,
                                                         const uint32_t ipProp) const
    {
        ACL_LOG_DEBUG("start to execute aclvencSetChannelDescIpProp, ipProp %u", ipProp);
        ACL_REQUIRES_NOT_NULL(channelDesc);

        {
            const std::unique_lock<std::mutex> locker{channelDesc->mutexForTLVMap};
            std::map<acl::VencTLVType, acl::VencChannelDescTLVParam>::const_iterator it =
                    channelDesc->tlvParamMap.find(VENC_IP_PROP);
            if (it == channelDesc->tlvParamMap.cend()) {
                VencChannelDescTLVParam vencTLVParam;
                const std::shared_ptr<aicpu::dvpp::VencIpProportion> ipProportion =
                        std::make_shared<aicpu::dvpp::VencIpProportion>();
                ACL_REQUIRES_NOT_NULL(ipProportion);
                ipProportion->maxIpProp = ipProp;
                vencTLVParam.value = static_cast<std::shared_ptr<void>>(ipProportion);
                vencTLVParam.valueLen = sizeof(aicpu::dvpp::VencIpProportion);
                channelDesc->tlvParamMap[VENC_IP_PROP] = vencTLVParam;
            } else {
                aicpu::dvpp::VencIpProportion *const ipProportion =
                        static_cast<aicpu::dvpp::VencIpProportion *>(it->second.value.get());
                ACL_REQUIRES_NOT_NULL(ipProportion);
                ipProportion->maxIpProp = ipProp;
            }
        }

        return ACL_SUCCESS;
    }

    /**
     * Get output buffer size for venc channel desc.
     * @param channelDesc[IN] venc channel desc
     * @param isSupport[OUT] support flag
     * @return output buffer size
     */
    uint32_t VideoProcessor::aclvencGetChannelDescBufSize(const aclvencChannelDesc *const channelDesc,
                                                          bool &isSupport) const
    {
        (void)(channelDesc);
        (void)(isSupport);
        ACL_LOG_INNER_ERROR("[Unsupport][Feature]Getting BufSize for venc channel desc is "
                            "not supported in this version. Please check.");
        isSupport = false;
        return 0U;
    }

    /**
     * Get output buffer address for venc channel desc.
     * @param channelDesc[IN] venc channel desc
     * @param isSupport[OUT] support flag
     * @return output buffer addr
     */
    void *VideoProcessor::aclvencGetChannelDescBufAddr(const aclvencChannelDesc *const channelDesc,
                                                       bool &isSupport) const
    {
        (void)(channelDesc);
        (void)(isSupport);
        ACL_LOG_INNER_ERROR("[Unsupport][Feature]Getting BufAddr for venc channel desc "
                            "is not supported in this version. Please check.");
        isSupport = false;
        return nullptr;
    }

    /**
     * Get rc mode for venc channel desc.
     * @param channelDesc[IN] venc channel desc
     * @param isSupport[OUT] support flag
     * @return rc mode, default 0
     */
    uint32_t VideoProcessor::aclvencGetChannelDescRcMode(const aclvencChannelDesc *const channelDesc,
                                                         bool &isSupport) const
    {
        ACL_LOG_INFO("start to execute aclvencGetChannelDescRcMode");
        isSupport = true;
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("[Check][ChannelDesc]venc channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                                                              argList, argVal, 1U);
            return 0U;
        }

        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> locker{mutexMap};
            const auto &it = channelDesc->tlvParamMap.find(VENC_RATE_CONTROL);
            // no set venc rate control para, return 0
            if (it == channelDesc->tlvParamMap.end()) {
                return 0U;
            }

            aicpu::dvpp::VencRateControl *const vencRateControlPtr =
                    static_cast<aicpu::dvpp::VencRateControl *>(it->second.value.get());
            if (vencRateControlPtr == nullptr) {
                ACL_LOG_INNER_ERROR("[Check][VencRateControl]vencRateControlPtr ptr is null.");
                return 0U;
            }

            return vencRateControlPtr->rcMode;
        }
    }

    /**
     * Get source rate for venc channel desc.
     * @param channelDesc[IN] venc channel desc
     * @param isSupport[OUT] support flag
     * @return source rate, default 0
     */
    uint32_t VideoProcessor::aclvencGetChannelDescSrcRate(const aclvencChannelDesc *const channelDesc,
                                                          bool &isSupport) const
    {
        ACL_LOG_INFO("start to execute aclvencGetChannelDescSrcRate");
        isSupport = true;
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("[Check][ChannelDesc]venc channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                                                              argList, argVal, 1U);
            return 0U;
        }

        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> locker{mutexMap};
            const auto &it = channelDesc->tlvParamMap.find(VENC_RATE_CONTROL);
            // no set venc rate control para, return 0
            if (it == channelDesc->tlvParamMap.end()) {
                return 0U;
            }

            aicpu::dvpp::VencRateControl *const vencRateControlPtr =
                    static_cast<aicpu::dvpp::VencRateControl *>(it->second.value.get());
            if (vencRateControlPtr == nullptr) {
                ACL_LOG_INNER_ERROR("[Check][VencRateControl]vencRateControlPtr ptr is null.");
                return 0U;
            }

            return vencRateControlPtr->srcRate;
        }
    }

    /**
     * Get max bit rate for venc channel desc.
     * @param channelDesc[IN] venc channel desc
     * @param isSupport[OUT] support flag
     * @return max bit rate, default 0
     */
    uint32_t VideoProcessor::aclvencGetChannelDescMaxBitRate(const aclvencChannelDesc *const channelDesc,
                                                             bool &isSupport) const
    {
        ACL_LOG_INFO("start to execute aclvencGetChannelDescMaxBitRate");
        isSupport = true;
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("[Check][ChannelDesc]venc channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                                                              argList, argVal, 1U);
            return 0U;
        }

        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> locker{mutexMap};
            const auto &it = channelDesc->tlvParamMap.find(VENC_RATE_CONTROL);
            // no set venc rate control para, return 0
            if (it == channelDesc->tlvParamMap.end()) {
                return 0U;
            }

            aicpu::dvpp::VencRateControl *const vencRateControlPtr =
                    static_cast<aicpu::dvpp::VencRateControl *>(it->second.value.get());
            if (vencRateControlPtr == nullptr) {
                ACL_LOG_INNER_ERROR("[Check][VencRateControl]vencRateControlPtr ptr is null.");
                return 0U;
            }

            return vencRateControlPtr->maxBitRate;
        }
    }

    /**
     * Get ip proportion for venc channel desc.
     * @param channelDesc[IN] venc channel desc
     * @return I frame and P frame proportion
     */
    uint32_t VideoProcessor::aclvencGetChannelDescIPProp(const aclvencChannelDesc *const channelDesc) const {
        ACL_LOG_DEBUG("start to execute aclvencSetChannelDescIpProp.");
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("venc channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                                                              argList, argVal, 1U);
            return 0U;
        }

        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> locker{mutexMap};
            const auto &it = channelDesc->tlvParamMap.find(VENC_IP_PROP);
            // no set venc rate control para, return 0
            if (it == channelDesc->tlvParamMap.end()) {
                return 0U;
            }

            aicpu::dvpp::VencIpProportion *const ipProportion =
                    static_cast<aicpu::dvpp::VencIpProportion *>(it->second.value.get());
            if (ipProportion == nullptr) {
                ACL_LOG_ERROR("ipProportion ptr is null.");
                return 0U;
            }

            return ipProportion->maxIpProp;
        }
    }
    }
}